Skip to main content

Pesquisa — Desconto PIX + CrmBonus: fluxo atual e impacto do upsell

Data: 2026-05-15 Contexto: Task #193232 — Análise do fluxo de integração CRMBonus Fontes:

  • coezzion-service-checkout/src/
  • coezzion-service-cart/src/
  • coezzion-db-core/src/
  • coezzion-db-link/src/

Seção 1 — Fluxo PIX + CrmBonus (comportamento atual, sem upsell)

Como o desconto PIX é configurado

O desconto PIX é um percentual por loja, armazenado em StoresPayment.PixDiscountPercentage (decimal(5,2), nullable). Não é um valor fixo — é calculado sobre cart.ItemsTotal no momento em que o cliente escolhe PIX.

// coezzion-db-core/src/Core.OrgDB/Entities/StorePaymentModel.cs, linha 60
public decimal? PixDiscountPercentage { get; set; }

Onde o desconto PIX é persistido

Dois lugares:

EntidadeCamposQuando é gravado
PaymentsDataModel (tabela PaymentsData, banco zzlink)PixDiscountPercentage, PixDiscountValueQuando o cliente escolhe PIX (PixBraspagService.ApplyPixDiscount)
CartModel (tabela Carts, banco core)PixDiscountPercentage, PixDiscountValueApós captura — via fila AWS_SQS_CHANGE_CART_VALUES

Linha do tempo completa

[Vendedora cria cart com CrmBonus]
└─ cart.Total = ItemsTotal + Frete - CrmBonus.RescuedBonus
└─ cart.CrmBonus.Total = Total original (gravado uma vez, imutável)

[CreatePaymentCommandHandler — criação do pedido]
└─ baixa_bonus → CRM
valor_bruto = cart.Total ← SEM desconto PIX
bonus_resgatado = CrmBonus.RescuedBonus

[Cliente abre zzlink — GetCartInfo]
└─ Lê StoresPayment.PixDiscountPercentage
└─ Exibe simulação: TotalWhenPix = cart.Total - (ItemsTotal × %)
(apenas visual, cart.Total não é alterado aqui)

[Cliente escolhe PIX — PixBraspagService.CreateOrderBraspagAsync()]
└─ PixDiscountValue = round(ItemsTotal × PixDiscountPercentage / 100, 2)
└─ paymentData.Value -= PixDiscountValue ← valor real cobrado via PIX
└─ Persiste PixDiscountPercentage + PixDiscountValue em PaymentsData

[Cliente paga — PIX confirmado]

[PosCaptureService.ExecutePosCapture()]
├─ Passo 4: finaliza_compra → CRM
│ valor_bruto = cart.CrmBonus.Total ← valor congelado na criação, SEM desconto PIX
│ bonus_resgatado = CrmBonus.RescuedBonus

├─ Passo 5: IntegrationPdvEvent
│ PdvIntegrationValue = ItemsTotal - CrmBonus.RescuedBonus ← SEM desconto PIX
│ PixDiscountValue = calculado ← separado, para o PDV

└─ Passo 6: ExecutePaymentChangeEvent → fila SQS
└─ ValuesCartChangedEvent: Total + PixDiscountPercentage + PixDiscountValue
└─ CartService.Handle(UpdateCartValuesCommand)
└─ cart.Total atualizado com valor real pago (pós-PIX)
cart.PixDiscountPercentage e cart.PixDiscountValue gravados

Relação entre os dois descontos

O CalculateTotal() do CartModel não aplica desconto PIX — ele só deduz CrmBonus.RescuedBonus:

// coezzion-db-core/src/Core.OrgDB/Entities/CartModel.cs
public void CalculateTotal()
{
ItemsTotal = CartItems.Sum(p => p.CalculateTotal());
Total = ItemsTotal;
if (ShipmentValue is > 0) Total += ShipmentValue.Value;
if (CrmBonus is { RescuedBonus: > 0 })
{
Total -= CrmBonus.RescuedBonus.Value;
PdvIntegrationValue -= CrmBonus.RescuedBonus.Value;
}
// desconto PIX não está aqui
}

O desconto PIX é aplicado diretamente no paymentData.Value no momento da criação da ordem PIX — fora do ciclo de vida do cart.Total.

Conclusão da Seção 1

Os dois descontos operam em campos diferentes, em momentos diferentes, sem interferência mútua:

  • CrmBonus.RescuedBonus é deduzido do cart.Total na criação do pedido e enviado ao CRM como bonus_resgatadofixo.
  • PixDiscountValue é calculado no momento da escolha do PIX, aplicado no paymentData.Value, e só chega ao cart.Total após a captura via fila — posterior ao CRM.

O CRM nunca recebe o desconto PIX — nem no baixa_bonus nem no finaliza_compra. Isso é consistente e intencional no fluxo atual: o valor_bruto representa o valor do pedido antes de descontos de meio de pagamento.

Não há conflito hoje.


Seção 2 — Impacto do upsell no cenário combinado (PIX + CrmBonus + itens adicionados)

O que muda com upsell

Com a feature de upsell, o cliente pode adicionar itens ao carrinho após a criação do pedido (após baixa_bonus já ter sido executado). Isso altera cart.ItemsTotal e cart.Total, mas não altera cart.CrmBonus.Total nem CrmBonus.RescuedBonus — ambos são imutáveis.

Seja:

  • T0 = cart.Total no momento da criação do pedido (base do baixa_bonus)
  • ΔItem = valor do item adicionado via upsell
  • B = CrmBonus.RescuedBonus (imutável)
  • P% = PixDiscountPercentage da loja

Evolução dos valores ao longo do fluxo com upsell

Momentocart.Totalcart.ItemsTotalcart.CrmBonus.TotalDesconto PIX calculado
Criação do pedidoT0T0 + B (aprox.)T0 (congelado)
Após upsellT0 + ΔItemT0 + B + ΔItem (aprox.)T0 (não muda)
Cliente escolhe PIXT0 + ΔItemT0 + B + ΔItemT0 (não muda)(T0 + B + ΔItem) × P%
Capturaefetivado
finaliza_compra (passo 4)T0 + ΔItemT0 ← enviado ao CRMjá incluído na base do PIX
Cart atualizado via fila (passo 6)T0 + ΔItem - PIXT0 (não muda)gravado no cart

As três divergências acumuladas

Com upsell ativo, as chamadas ao CRM ficam assim:

baixa_bonus (criação do pedido — antes do upsell):

valor_bruto = T0 ← valor do pedido original, sem o item de upsell
bonus_resgatado = B

finaliza_compra (após captura — depois do upsell e do PIX):

valor_bruto = cart.CrmBonus.Total = T0 ← valor congelado, sem upsell, sem PIX
bonus_resgatado = B

Valor real pago pelo cliente:

valor real = T0 + ΔItem - B - (T0 + B + ΔItem) × P%

Resultado: o CRM processa a efetivação com valor_bruto = T0, enquanto o cliente pagou um valor diferente nas duas direções — maior (por causa do upsell) e menor (por causa do PIX). O CRM não vê nenhum dos dois ajustes.

Impacto no cálculo do desconto PIX com upsell

O desconto PIX é calculado sobre cart.ItemsTotal no momento em que o cliente escolhe PIX. Com upsell, esse ItemsTotal já inclui o item adicionado — então o upsell aumenta a base de cálculo do desconto PIX:

Sem upsell: PixDiscountValue = ItemsTotal_original × P%
Com upsell: PixDiscountValue = (ItemsTotal_original + ΔItem) × P%

O cliente recebe desconto PIX também sobre o item de upsell. Isso é provavelmente correto do ponto de vista de negócio, mas não há nada no fluxo atual que impeça ou sinalize essa situação.

Resumo dos riscos combinados

RiscoOrigemImpacto no CRM
valor_bruto do baixa_bonus não inclui o item de upsellbaixa_bonus usa cart.Total no momento da criaçãoCRM reservou bônus com valor menor que o pedido final
valor_bruto do finaliza_compra não inclui upsell nem PIXfinaliza_compra usa cart.CrmBonus.Total congeladoCRM efetiva com valor diferente do valor real pago
Desconto PIX cresce com o upsellbase de cálculo é ItemsTotal no momento da escolha PIXDesconto maior do que seria sem upsell — impacto na margem da loja

Ponto crítico: o CRM valida valor_bruto entre as chamadas?

A questão central permanece sem resposta (ver Ponto 1 em task-193232-checkout-crm.md):

  • o CRM rejeita finaliza_compra se o valor_bruto for diferente do baixa_bonus?
  • No cenário combinado PIX + CrmBonus + upsell, a diferença entre os dois valor_bruto é máxima — inclui ΔItem e o tempo entre as chamadas é maior (upsell acontece entre as duas).